﻿Imports PTIC_GestionBDD
Imports PTIC_Util
Imports PTIC_Util.GestionCalculs
Imports Actuariat.Comptes
Imports Actuariat
Imports System.Data
Imports OMANE.Common.Model.Interfaces
Imports OMANE.Common.Model.Parametrage

Namespace moteurTauxGaranti1
    ''' <summary>
    ''' Moteur de calcul du taux garanti par la méthode de l'équilibre technique
    ''' </summary>
    ''' <remarks></remarks>
    Public Class Moteur_Methode1
        Inherits Traitement
        Implements IIntegMoteur_MethodeEqTarif

        Dim Optimise As Boolean = False
        Dim TempsChgtTable As Double = 0
        Dim TimeChgtTable1 As Double = 0
        Dim TimeChgtTable2 As Double = 0
        Dim TempsFonctCalculPrinc As Double = 0
        Dim TimeFonctCalculPrinc1 As Double = 0
        Dim TimeFonctCalculPrinc2 As Double = 0
        Dim TempsFonctCalculSecondaire As Double = 0
        Dim TimeFonctCalculSecondaire1 As Double = 0
        Dim TimeFonctCalculSecondaire2 As Double = 0

#Region "Variables de classe"
        'Collection de paramètres de l'étude en cours
        Protected _coll_param As ParametresList
        'Table contenant les segments et toutes leurs caractéristiques
        Protected _tble_travail As DataTable
        'Tables de mortalité H/F, maintien INCAP/INVAL hors franchise, coefficients de réduction à appliquer à cause de la franchise
        Protected m_tble_mortalite_H As ITableMortalite, m_tble_mortalite_F As ITableMortalite
        Private m_TbleINCINVTaux As ITableMaintienINCINV_Tx
        Private m_TbleINCINVFra As ITableMaintienINCINV_Fra
        'Résultats du calcul / Scénario central / Simulations
        Protected _resultatsCalcul As resultatsMoteur1
        Protected _scenarioCentral As scenarioCentralMoteur1
        Protected _simulations As simulationsMoteur1
#End Region

#Region "Création d'une instance"
        ''' <summary>
        ''' Constructeur
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New(ByVal nom As String, _
                       ByVal coll_Param As ParametresList, _
                       ByVal TraitEntreeModelEqTarif As Traitement, _
                       ByVal DataSetOMANE As DataSet, _
                       ByVal Referentiel As IReferentielOMANE)
            MyBase.New(nom, Nothing)
            m_Referentiel = Referentiel
            m_TraitementEntree = TraitEntreeModelEqTarif
            AddHandler m_TraitementEntree.EtatCalculDataTableAChange, AddressOf onTraitEntree_EtatCalculDataTableChanged

            m_DataSet = DataSetOMANE
            'Collection de paramètres afférents à l'étude en cours
            _coll_param = coll_Param
            'Objet permettant de stocker les résultats du moteur et du scénario central
            _resultatsCalcul = New resultatsMoteur1()
            _scenarioCentral = New scenarioCentralMoteur1(Me)
            _simulations = New simulationsMoteur1(Me)
            _simulations.AjouteFonctionCalculIntermediaire(_scenarioCentral)
            addHandlers()
        End Sub
#End Region

#Region "Propriétés"
        Private m_Referentiel As IReferentielOMANE
        Public ReadOnly Property Referentiel As IReferentielOMANE Implements IIntegMoteur_MethodeEqTarif.Referentiel
            Get
                Return m_Referentiel
            End Get
        End Property

        Private m_DataSet As DataSet
        Public ReadOnly Property DataSetOMANE As DataSet Implements IIntegMoteur_MethodeEqTarif.DataSetOMANE
            Get
                Return m_DataSet
            End Get
        End Property

        Private m_TraitementEntree As Traitement
        Public ReadOnly Property TraitementEntree As Traitement Implements IIntegMoteur_MethodeEqTarif.TraitementEntree
            Get
                Return m_TraitementEntree
            End Get
        End Property

        ''' <summary>
        ''' Liste des paramètres utilisés dans les calculs
        ''' </summary>
        ''' <remarks></remarks>
        Public Property listeParametres() As ParametresList Implements IIntegMoteur_MethodeEqTarif.listeParametres
            Get
                Return _coll_param
            End Get
            Set(ByVal value As ParametresList)
                If Not value Is _coll_param Then
                    RemoveHandlersListeParametres()
                    _coll_param = value
                    addHandlersListeParametres()
                End If
            End Set
        End Property

        ''' <summary>
        ''' Etat de calcul du scénario central
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property etatCalculScenCentral() As ValueEtatCalcul Implements IIntegMoteur_MethodeEqTarif.etatCalculScenCentral
            Get
                Return _scenarioCentral.EtatCalcul
            End Get
        End Property

        ''' <summary>
        ''' Etat de calcul des simulations
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property etatCalculSimulations() As ValueEtatCalcul Implements IIntegMoteur_MethodeEqTarif.etatCalculSimulations
            Get
                Return simulations.EtatCalcul
            End Get
        End Property

        ''' <summary>
        ''' Table en entrée utilisée dans la procédure de calcul et issue des encours retraités
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property tableTravail() As DataTable Implements IIntegMoteur_MethodeEqTarif.tableTravail
            Get
                Return _tble_travail
            End Get
        End Property

        ''' <summary>
        ''' Scénario central du moteur de calcul 1
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property ScenarioCentral As scenarioCentralMoteur1 Implements IIntegMoteur_MethodeEqTarif.ScenarioCentral
            Get
                Return _scenarioCentral
            End Get
        End Property

        ''' <summary>
        ''' Prime pure résultant du dernier calcul du moteur
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property PPurePf() As Double Implements IIntegMoteur_MethodeEqTarif.PPurePf
            Get
                Return _resultatsCalcul.PPurePf
            End Get
        End Property

        ''' <summary>
        ''' Prime technique résultant du dernier calcul du moteur
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property PTechPf() As Double Implements IIntegMoteur_MethodeEqTarif.PTechPf
            Get
                Return _resultatsCalcul.PTechPf
            End Get
        End Property

        ''' <summary>
        ''' Somme des capitaux résultant du dernier calcul du moteur
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property sommeCSR() As Double Implements IIntegMoteur_MethodeEqTarif.sommeCSR
            Get
                Return _resultatsCalcul.sommeCSR
            End Get
        End Property

        ''' <summary>
        ''' Somme des capitaux sous rique du scénario central
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property sommeCSR_ScenCentral() Implements IIntegMoteur_MethodeEqTarif.sommeCSR_ScenCentral
            Get
                Return _scenarioCentral.resultats.sommeCSR
            End Get
        End Property

        ''' <summary>
        ''' Simulations attachées au moteur de calcul
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property simulations() As IsimulationsMoteur1 Implements IIntegMoteur_MethodeEqTarif.simulations
            Get
                Return _simulations
            End Get
        End Property
#End Region

#Region "Calculs"

#Region "Table en entrée + Tables de travail"
        ''' <summary>
        ''' Initialisation des tables de travail nécessaires au modèle 1
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub init_tbles_travail(ByVal Referentiel As IReferentielOMANE) Implements IIntegMoteur_MethodeEqTarif.init_tbles_travail

            TableMortalite_H_Initialize(Referentiel)
            TableMortalite_F_Initialize(Referentiel)
            TableMaintienINCINV_Fra_Initialize(Referentiel)
            TableMaintienINCINV_Tx_Initialize(Referentiel)

            TraitementEntree.Calculer_DataTable()
            _tble_travail = TraitementEntree.DataTableResultat
            If DataSetOMANE.Tables.Contains(_tble_travail.TableName) Then DataSetOMANE.Tables.Remove(_tble_travail.TableName)
            DataSetOMANE.Tables.Add(_tble_travail)
        End Sub

        Private Sub TableMortalite_H_Initialize(ByVal Referentiel As IReferentielOMANE)
            Dim NomTableMortaliteH As String = _
                (From InfoTable As IInfoTableReferentiel In Referentiel.TablesMortalite.InfoTables
                Select InfoTable
                Where InfoTable.NomFichier = listeParametres.Table_Mortalite_H.ValeurUnique.ToString).AsEnumerable.FirstOrDefault.NomTable

            m_tble_mortalite_H = Referentiel.TablesMortalite.Factory.Item(NomTableMortaliteH)
        End Sub
        Private Sub TableMortalite_F_Initialize(ByVal Referentiel As IReferentielOMANE)
            Dim NomTableMortaliteF As String = _
                (From InfoTable As IInfoTableReferentiel In Referentiel.TablesMortalite.InfoTables
                Select InfoTable
                Where InfoTable.NomFichier = listeParametres.Table_Mortalite_F.ValeurUnique.ToString).AsEnumerable.FirstOrDefault.NomTable

            m_tble_mortalite_F = Referentiel.TablesMortalite.Factory.Item(NomTableMortaliteF)
        End Sub
        Private Sub TableMaintienINCINV_Fra_Initialize(ByVal Referentiel As IReferentielOMANE)
            Dim NomTableMaintienINCINV_Fra = _
                (From InfoTable As IInfoTableReferentiel In Referentiel.TablesINCINV_Fra.InfoTables
                Select InfoTable
                Where InfoTable.NomFichier = listeParametres.tble_maintien_incinvFRA.ValeurUnique.ToString).AsEnumerable.FirstOrDefault.NomTable

            m_TbleINCINVFra = Referentiel.TablesINCINV_Fra.Factory.Item(NomTableMaintienINCINV_Fra)
        End Sub
        Private Sub TableMaintienINCINV_Tx_Initialize(ByVal Referentiel As IReferentielOMANE)
            Dim NomTableMaintienINCINV_Tx = _
                (From InfoTable As IInfoTableReferentiel In Referentiel.TablesINCINV_Tx.InfoTables
                 Select InfoTable
                 Where InfoTable.NomFichier = listeParametres.Tble_maintien_incinv.ValeurUnique).AsEnumerable.FirstOrDefault.NomTable

            m_TbleINCINVTaux = Referentiel.TablesINCINV_Tx.Factory.Item(NomTableMaintienINCINV_Tx)
        End Sub
#End Region

#Region "Héritage classe traitement"
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <remarks></remarks>
        Protected Overrides Sub execute_DataTable()
            MsgBox("Fonction à modifier")
        End Sub

        'Public Overrides Function execute_DataTableToDgv(ByVal stockageBDDlocale As Boolean, ByVal dgv As System.Windows.Forms.DataGridView) As System.Data.DataTable
        '    MsgBox("La fonction execute_DataTableToDgv du moteur de calcul 1 est en cours de développement")
        '    Return Nothing
        'End Function

        ''' <summary>
        ''' 
        ''' </summary>
        ''' <remarks></remarks>
        Protected Overrides Sub execute_BDD()
            'Vérifier que le traitement est à jour dans la base de données
        End Sub
#End Region

        ''' <summary>
        ''' Permettant de calculer le scénario central
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub calculerScenarioCentral() Implements IIntegMoteur_MethodeEqTarif.calculerScenarioCentral
            _scenarioCentral.Calculer()
        End Sub

        ''' <summary>
        ''' Permettant de calculer toutes les simulations
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub calculerSimulations() Implements IIntegMoteur_MethodeEqTarif.calculerSimulations
            simulations.Calculer()
        End Sub

        ''' <summary>
        ''' Permet d'initialiser la procédure de calcul
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub calculeInit() Implements IIntegMoteur_MethodeEqTarif.calculeInit

            If Optimise Then
                TempsChgtTable = 0
                TimeChgtTable1 = 0
                TimeChgtTable2 = 0
                TempsFonctCalculPrinc = 0
                TimeFonctCalculPrinc1 = 0
                TimeFonctCalculPrinc2 = 0
                TempsFonctCalculSecondaire = 0
                TimeFonctCalculSecondaire1 = 0
                TimeFonctCalculSecondaire2 = 0
                TimeChgtTable1 = Timer
            End If

            init_tbles_travail(Referentiel)

            _coll_param.MAJ_CollParamDeclUniq(1)
            Dim parametres_decl As Hashtable = _coll_param.GetParamDecl
            Dim parametres_uniq As Hashtable = _coll_param.getParamUniq
            'Mise à jour des valeurs en cours de tous les paramètres uniques
            For Each p As IParametre In parametres_uniq.Values
                p.ValeurEnCoursAsObject = p.ValeurUniqueAsObject
            Next

            'Création des relations entre les paramètres déclinés et la table de travail
            '_coll_param.ParamRelationsV2()
            _coll_param.ParamRelationsV2(parametres_decl, _tble_travail, DataSetOMANE)

        End Sub

        ''' <summary>
        ''' Procédure de calcul, utilisée à la fois par le scénario central et les simulations
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub calcule(ByVal isScenarioCentral As Boolean, Optional SimulChoc As SimulationChoc = Nothing) Implements IIntegMoteur_MethodeEqTarif.calcule

            'Le tableau PrimesParCSR contient, pour chaque segment, les informations suivantes :
            '   - 1ere colonne : les CSR (indice 0)
            '   - 2eme colonne : la prime pure (indice 1)
            '   - 3eme colonne : la prime technique (indice 2)
            Dim PrimesParCSR(_tble_travail.Rows.Count - 1, 2)
            Dim parametres_decl As Hashtable = _coll_param.GetParamDecl
            Dim parametres_uniq As Hashtable = _coll_param.getParamUniq
            Dim ageSous_Actu As Double, _
                nbPer As Double, _
                txNomPer As Double, _
                txMort_Actu As Double, _
                ageFinDC As Double, _
                ageFinINCINV As Double
            Dim TableMort As ITableMortalite
            Dim sommeCSR As Double = 0, CI As Double = 1, PPures() As Double, numSegment As Integer = 0
            Dim PPSegment As Double, PPureDC As Double, PPureINCINV As Double

            If isScenarioCentral Then calculeTableTravailAjouteColonnes()

            If Optimise Then
                TimeChgtTable2 = Timer
                TempsChgtTable = TimeChgtTable2 - TimeChgtTable1
                MsgBox("Le nombre total d'itérations à réaliser est de " & _tble_travail.Rows.Count & vbCrLf & _
                       "Le temps de chargement des tables de travail a été de " & TempsChgtTable)
                TimeFonctCalculPrinc1 = Timer
            End If

            Dim compteur As Integer = 0
            Dim TempsDeb As Double = Timer
            Dim TempsFin As Double

            For Each r As DataRow In _tble_travail.Rows

                If Optimise Then
                    compteur += 1
                    If compteur = 100 Then
                        TempsFin = Timer
                        Dim TempsEcouleSec As Double = TempsFin - TempsDeb
                        Dim TempsEstimeMin As Double = ((TempsEcouleSec / compteur) * _tble_travail.Rows.Count) / 60
                        TimeFonctCalculPrinc2 = Timer
                        TempsFonctCalculPrinc = TempsFonctCalculPrinc + (TimeFonctCalculPrinc2 - TimeFonctCalculPrinc1)
                        MsgBox("Vous avez atteint la 100ème itération en " & TempsFin - TempsDeb & " secondes." & vbCrLf & _
                               "Le temps estimé (en minutes) pour effectuer le calcul est de " & TempsEstimeMin & vbCrLf & _
                               "Le % de temps passé dans la fonction principale est de : " & TempsFonctCalculPrinc / (TempsFonctCalculPrinc + TempsFonctCalculSecondaire) & vbCrLf & _
                               "Le % temps passé dans la fonction secondaire est de : " & TempsFonctCalculSecondaire / (TempsFonctCalculPrinc + TempsFonctCalculSecondaire))
                    End If
                End If


                'Mise à jour des valeurs en cours des paramètres déclinés (y compris sensibilités)
                For Each p As IParametre In parametres_decl.Values
                    p.ValeurEnCoursAsObject = r.GetChildRows("relParam" & p.Nom)(0)(p.Nom)
                Next

                'Mise à jour des paramètres nécessaires au calcul de l'échéancier
                sommeCSR = sommeCSR + r(nomSumCSR)
                txMort_Actu = _coll_param.TxMort_Actu.ValeursEnCours

                If r(nomSexeAssu) = "H" Then
                    TableMort = m_tble_mortalite_H
                Else
                    TableMort = m_tble_mortalite_F
                End If

                ageSous_Actu = rechercheVdoubleMin(TableMort.DataTable, _
                    _coll_param.TxMort_Actu.ValeursEnCours, _
                    nomTxMortAn, _
                    nomAgeAnEntier)

                nbPer = CType(_coll_param.Duree_Actu.ValeursEnCours, Integer)
                txNomPer = (1 + _coll_param.TxNom_Actu.ValeursEnCours) ^ (1 / 12) - 1
                ageFinDC = _coll_param.Age_FinDC.ValeursEnCours
                ageFinINCINV = _coll_param.Age_FinINCINV.ValeursEnCours


                'Calcul des primes pures DC et INC/INV
                PPures = PP_DC_INCINV_OutilsNA(nbPer,
                                               txNomPer,
                                               CI,
                                               ageSous_Actu,
                                               r("sexe_assu"),
                                               ageFinDC,
                                               ageFinINCINV,
                                               TableMort, m_TbleINCINVFra, m_TbleINCINVTaux)


                PPureDC = PPures(0)
                If r("id_option") = "DC/PTIA" Then
                    PPureINCINV = 0
                Else
                    PPureINCINV = PPures(1)
                End If

                'Calcul de la prime pure du segment
                PPSegment = PPureDC * 12 _
                * (1 + _coll_param.Tx_PrixGarantiePTIA.ValeursEnCours) _
                + PPureINCINV * 12 _
                * (1 + _coll_param.Tx_chgtSecuINCINV.ValeursEnCours) _
                * (1 - _coll_param.Tx_abat_MalaNonObje.ValeursEnCours) _
                * (1 - _coll_param.Tx_abat_ExclPerteRev.ValeursEnCours)


                'Calcul des primes technique DC et INC/INV
                Dim Adc, Bdc, PtechDC, Aincinv, Bincinv, PtechINCINV As Double
                Adc = -(r(nomPourDC_Derog_Actu) * r(nomPComDC_Derog_Actu) _
                        + (1 - r(nomPourDC_Derog_Actu)) * r(nomPComDC_Non_Derog_Actu))
                Bdc = -(1 - _coll_param.Tx_fraiGestA.ValeursEnCours) * Adc
                PtechDC = _coll_param.Tx_CommiContA.ValeursEnCours * Adc _
                          - (1 - _coll_param.Tx_fraiGestA.ValeursEnCours) * Adc

                Aincinv = -(r(nomPourINCINV_Derog_Actu) * r(nomPComINCINV_Derog_Actu) _
                            + (1 - r(nomPourINCINV_Derog_Actu)) * r(nomPComINCINV_Non_Derog_Actu)) _
                            / (1 + _coll_param.Tx_TaxeAssu.ValeursEnCours)

                Bincinv = -(1 - _coll_param.Tx_fraiGestA.ValeursEnCours) * Aincinv
                PtechINCINV = _coll_param.Tx_CommiContA.ValeursEnCours _
                              * Aincinv - (1 - _coll_param.Tx_fraiGestA.ValeursEnCours) * Aincinv

                PrimesParCSR(numSegment, 0) = r(nomSumCSR)
                PrimesParCSR(numSegment, 1) = PPSegment
                If r("id_option") = "DC/PTIA" Then
                    PrimesParCSR(numSegment, 2) = PtechDC
                Else
                    PrimesParCSR(numSegment, 2) = PtechDC + PtechINCINV
                End If

                If isScenarioCentral Then
                    r(nomTxMort_Actu) = _coll_param.TxMort_Actu.ValeursEnCours
                    r("AGESOUS_ACTU") = ageSous_Actu
                    r(nomDuree_Actu) = nbPer
                    r(nomTxNom_Actu) = _coll_param.TxNom_Actu.ValeursEnCours
                    r(nomAge_FinDC) = _coll_param.Age_FinDC.ValeursEnCours
                    r(nomAge_FinINCINV) = _coll_param.Age_FinINCINV.ValeursEnCours
                    r(nomTx_mensEntreeINCINV) = _coll_param.Tx_mensEntreeINCINV.ValeursEnCours
                    r(nomTx_TechA) = _coll_param.Tx_TechA.ValeursEnCours
                    r("PP_DC") = PPureDC
                    r("PP_INCINV") = PPureINCINV
                    r("PP_SEGMENT") = PPSegment
                    r("PTECH_SEGMENT") = PrimesParCSR(numSegment, 2)
                    r(nomTx_abat_ExclPerteRev) = _coll_param.Tx_abat_ExclPerteRev.ValeursEnCours
                    r(nomTx_abat_MalaNonObje) = _coll_param.Tx_abat_MalaNonObje.ValeursEnCours
                    r(nomTx_chgtSecuINCINV) = _coll_param.Tx_chgtSecuINCINV.ValeursEnCours
                    r(nomTx_fraiGestA) = _coll_param.Tx_fraiGestA.ValeursEnCours
                    r(nomTx_PrixGarantiePTIA) = _coll_param.Tx_PrixGarantiePTIA.ValeursEnCours
                    r(nomTx_TaxeAssu) = _coll_param.Tx_TaxeAssu.ValeursEnCours
                    r(nomTx_CommiContA) = _coll_param.Tx_CommiContA.ValeursEnCours

                    'Remplissage des colonnes des paramètres déclinés
                    For Each p As IParametre In parametres_decl.Values
                        r(p.Nom) = p.ValeurEnCoursAsObject
                    Next
                End If

                numSegment = numSegment + 1

            Next

            Dim pTechPf As Double = 0
            Dim pPurePf As Double = 0
            Dim poidsCSR As Double = 0
            For i As Integer = 0 To numSegment - 1
                poidsCSR = PrimesParCSR(i, 0) / sommeCSR
                pPurePf = pPurePf + PrimesParCSR(i, 1) * poidsCSR
                pTechPf = pTechPf + PrimesParCSR(i, 2) * poidsCSR
            Next

            If isScenarioCentral Then
                For Each r As DataRow In _tble_travail.Rows
                    'On ajoute une colonne poids à chaque segment du portefeuille
                    r("POIDS_CSR") = r(nomSumCSR) / sommeCSR
                    'pTechPf = pTechPf + r("PTECH_SEGMENT") * r("POIDS_CSR")
                    'pPurePf = pPurePf + r("PP_SEGMENT") * r("POIDS_CSR")
                Next
            End If

            _resultatsCalcul.PPurePf = pPurePf
            _resultatsCalcul.PTechPf = pTechPf
            _resultatsCalcul.sommeCSR = sommeCSR

        End Sub

        ''' <summary>
        ''' Permet de rétablir l'environnement de travail à la fin de la procédure de calcul
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub calculeCloture() Implements IIntegMoteur_MethodeEqTarif.calculeCloture
            Dim parametres_decl As Hashtable = _coll_param.GetParamDecl
            'Suppression des relations créées suite à la détermination des paramètres non uniques
            _coll_param.SupprParamRelations(parametres_decl, DataSetOMANE)
        End Sub

#Region "Fonctions privées spécifiques à la méthode de l'équilibre tarifaire et intervenant dans les calculs"
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <remarks></remarks>
        Private Function PP_DC_INCINV_OutilsNA(ByVal nbPer As Integer, _
                                               ByVal txNomPer As Double, _
                                               ByVal CI As Double, _
                                               ByVal ageSous As Integer, _
                                               ByVal sexeAssu As String,
                                               ByVal ageFinDC As Double,
                                               ByVal ageFinINCINV As Double,
                                               ByVal TableMort As ITableMortalite,
                                               ByVal TableMaintINCINV_Fra As ITableMaintienINCINV_Fra,
                                               ByVal TableMaintINCINV_Tx As ITableMaintienINCINV_Tx) As Double()

            'Calcul de la prime pure DC - Pour que l'outil soit plus rapide, on raisonne sur des tableaux
            'et non pas sur des objets
            'Le tableau contient une ligne par période -> dans la 1ere version, le raisonnement
            'est fait sur du mensuel
            'L'échéancier se présente de la façon suivante :
            '   - Colonne 0 : le CRD de la (i+1)ème période (le tableau commence à l'indice 0)
            '   - Colonne 1 : l'age de l'assuré en début de période
            '   - Colonne 2 : le taux de mortalité mensuel de la période (s'il s'agit d'un homme ou d'une femme)
            '   - Colonne 3 : la probabilité de survie dans le crédit jusqu'au début de la période
            '   - Colonne 4 : la valeur probable de la prestation
            '   - Colonne 5 : la valeur actuelle probable de la prestation DC
            '   - Colonne 6 : la valeur actuelle probable de l'assiette de prime
            '   - Colonne 7 : la valeur actuelle probable de la prestation probable en INC/INV

            Dim echeancier(nbPer - 1, 7) As Double
            Dim VAP_deces As Double = 0, VAP_INCINV As Double = 0, VAP_assiette As Double = 0
            Dim mensualite As Double = (-1) * Microsoft.VisualBasic.Pmt(txNomPer, nbPer, CI, , DueDate.EndOfPeriod)
            Dim txTechA As Double = _coll_param.Tx_TechA.ValeursEnCours

            'Initialisation de l'échéancier
            echeancier(0, 0) = CI
            echeancier(0, 1) = ageSous
            'Remarque1 : Attention au calcul des taux mensuels dans l'outil NA
            'Remarque2 : Attention au calcul des âges dans l'outil NA
            echeancier(0, 2) = TableMort.TxMortalite(ageSous) / 12
            ' echeancier(0, 2) = IIf(sexeAssu = "H", m_tble_mortalite_H, m_tble_mortalite_F).Rows(ageSous)(nomTxMortAn) / 12
            echeancier(0, 3) = 1
            echeancier(0, 4) = (echeancier(0, 0) * echeancier(0, 2) * echeancier(0, 3))
            echeancier(0, 5) = CI * echeancier(0, 2) * echeancier(0, 3) _
                               * (1 + txTechA) ^ (-(0.5) / 12)
            echeancier(0, 6) = CI * (1 + txTechA) ^ (-(0.5) / 12)
            echeancier(0, 7) = 0

            VAP_deces = echeancier(0, 5)
            VAP_assiette = echeancier(0, 6)

            'Récurrence sur l'échéancier
            For i = 1 To nbPer - 1



                Dim age As Double = ageSous + i / 12

                If txNomPer = 0 Then txNomPer = 0.000000001
                'If txNomPer = Double.Epsilon Then
                'End If

                echeancier(i, 0) = CI * ((1 + txNomPer) ^ nbPer - (1 + txNomPer) ^ i) / ((1 + txNomPer) ^ nbPer - 1)
                echeancier(i, 1) = ageSous + CType(i / 12, Integer)

                ' ********************************************************


                'echeancier(i, 2) = (IIf(sexeAssu = "H", _tble_mortalite_H, _table_mortalite_F).Rows(ageSous + CType((i / 12) + 0.000000001, Integer))((nomTxMortAn))) / 12
                Dim AgeRech As Integer = ageSous + CType((i / 12) + 0.000000001, Integer)

                'TimeFonctCalculSecondaire1 = Timer
                'TimeFonctCalculPrinc2 = Timer
                'TempsFonctCalculPrinc = TempsFonctCalculPrinc + (TimeFonctCalculPrinc2 - TimeFonctCalculPrinc1)

                'TimeFonctCalculPrinc1 = Timer
                'TimeFonctCalculSecondaire2 = Timer
                'TempsFonctCalculSecondaire = TempsFonctCalculSecondaire + (TimeFonctCalculSecondaire2 - TimeFonctCalculSecondaire1)

                echeancier(i, 2) = TableMort.TxMortalite(AgeRech) / 12 'm_tble_mortalite_H.Rows(AgeRech)(nomTxMortAn)

                ' ********************************************************


                echeancier(i, 3) = echeancier(i - 1, 3) * (1 - echeancier(i, 2))
                'Attention, l'actualisation de la valeur probable des prestations DC
                's'effectue en taux proportionnel (tx_annuel/12). Ce n'est pas cohérent avec le calcul des CRD
                'Hypothèse de paiement des sinistres en milieu de période

                echeancier(i, 4) = (echeancier(i, 0) * echeancier(i, 2) * echeancier(i, 3))
                If age < ageFinDC Then
                    echeancier(i, 5) = (echeancier(i, 0) * echeancier(i, 2) * echeancier(i, 3)) * (1 + txTechA) ^ (-(i + 0.5) / 12)
                Else
                    echeancier(i, 5) = 0
                End If
                echeancier(i, 6) = CI * echeancier(i, 3) * (1 + txTechA) ^ (-(i + 0.5) / 12)

                'Prestation probable en INCINV (dans la version 1, on fixe la franchise à 3 mois)
                If i <= 3 Or age >= ageFinINCINV Then
                    echeancier(i, 7) = 0
                Else
                    'On calcule, de même que dans le fichier de recette, durée-numPériode
                    Dim dureeCouvINC As Integer = Math.Min(36, nbPer - i)
                    Dim tx_HorsFra As Double = TableMaintINCINV_Tx.ProbaMaintien(dureeCouvINC, ageSous)
                    'On récupère le taux d'entrée (ici 0,5 pour simplifier)
                    Dim tx_entree As Double = _coll_param.Tx_mensEntreeINCINV.ValeursEnCours

                    'On applique un taux constant car la franchise est fixée à 3 mois
                    Dim tx_reducFRA As Double = TableMaintINCINV_Fra.TauxAbattement_Fra(3, ageSous)

                    'On mpultiplie par la proba de survie dans le crédit
                    echeancier(i, 7) = (tx_entree * mensualite * tx_HorsFra * tx_reducFRA * echeancier(i, 3)) * (1 + txTechA) ^ (-(i + 0.5) / 12)

                End If
                VAP_deces = VAP_deces + echeancier(i, 5)
                VAP_assiette = VAP_assiette + echeancier(i, 6)
                VAP_INCINV = VAP_INCINV + echeancier(i, 7)
            Next

            Dim result(1) As Double
            result(0) = VAP_deces / VAP_assiette
            result(1) = VAP_INCINV / VAP_assiette

            Return result

        End Function

        ''' <summary>
        ''' 
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub calculeTableTravailAjouteColonnes()
            'Ajout à la table de travail des colonnes nécessaires au moteur de calcul
            With _tble_travail.Columns
                If Not .Contains(nomDuree_Actu) Then .Add(nomDuree_Actu, GetType(Double))
                If Not .Contains(nomTxNom_Actu) Then .Add(nomTxNom_Actu, GetType(Double))
                If Not .Contains(nomTxMort_Actu) Then .Add(nomTxMort_Actu, GetType(Double))
                If Not .Contains(nomAge_FinDC) Then .Add(nomAge_FinDC, GetType(Integer))
                If Not .Contains(nomAge_FinINCINV) Then .Add(nomAge_FinINCINV, GetType(Integer))
                If Not .Contains(nomTx_mensEntreeINCINV) Then .Add(nomTx_mensEntreeINCINV, GetType(Double))
                If Not .Contains(nomTx_TechA) Then .Add(nomTx_TechA, GetType(Double))
                If Not .Contains(nomTx_abat_ExclPerteRev) Then .Add(nomTx_abat_ExclPerteRev, GetType(Double))
                If Not .Contains(nomTx_abat_MalaNonObje) Then .Add(nomTx_abat_MalaNonObje, GetType(Double))
                If Not .Contains(nomTx_chgtSecuINCINV) Then .Add(nomTx_chgtSecuINCINV, GetType(Double))
                If Not .Contains(nomTx_fraiGestA) Then .Add(nomTx_fraiGestA, GetType(Double))

                If Not .Contains(nomTx_PrixGarantiePTIA) Then .Add(nomTx_PrixGarantiePTIA, GetType(Double))
                If Not .Contains(nomTx_TaxeAssu) Then .Add(nomTx_TaxeAssu, GetType(Double))
                If Not .Contains(nomTx_CommiContA) Then .Add(nomTx_CommiContA, GetType(Double))

                If Not .Contains("PP_DC") Then .Add("PP_DC", GetType(Double))
                If Not .Contains("PP_INCINV") Then .Add("PP_INCINV", GetType(Double))
                If Not .Contains("AGESOUS_ACTU") Then .Add("AGESOUS_ACTU", GetType(Double))
                If Not .Contains("PP_SEGMENT") Then .Add("PP_SEGMENT", GetType(Double))
                If Not .Contains("PTECH_SEGMENT") Then .Add("PTECH_SEGMENT", GetType(Double))
                If Not .Contains("POIDS_CSR") Then .Add("POIDS_CSR", GetType(Double))
            End With
        End Sub
#End Region

#End Region

#Region "Traitement des évènements reçus de l'extérieur"

#Region "Gestion des Handles"
        ''' <summary>
        ''' Abonnement de la classe aux évènements qui lui sont utiles
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub addHandlers()
            'Placer le moteur 1 comme observateur de tous les paramètres influençant son calcul
            'Cette classe joue ici le rôle de médiateur et de façade
            AddHandler _scenarioCentral.EtatCalculChanged, AddressOf onScenarioCentralEtatCalculChanged
            AddHandler _simulations.EtatCalculChanged, AddressOf onSimulationsEtatCalculChanged
            addHandlersListeParametres()
        End Sub

        ''' <summary>
        ''' Abonnement de la classe aux évènements générés par les paramètres
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub addHandlersListeParametres()
            If Not _coll_param Is Nothing Then
                For Each param As BaseParametre In _coll_param.Values
                    If param.Methode_Cal(0) Then
                        AddHandler param.hasChanged, AddressOf onParametreChanged
                    End If
                Next
            End If
        End Sub

        ''' <summary>
        ''' Désabonnement de la classe aux évènements générés par les paramètres
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub RemoveHandlersListeParametres()
            If Not _coll_param Is Nothing Then
                For Each param As BaseParametre In _coll_param.Values
                    If param.Methode_Cal(0) Then RemoveHandler param.hasChanged, AddressOf onParametreChanged
                Next
            End If
        End Sub
#End Region

        Private Sub onScenarioCentralEtatCalculChanged(ByVal sender As Object, ByVal e As EventArgs)
            If _scenarioCentral.EtatCalcul <> ValueEtatCalcul.A_JOUR Then
                _simulations.Invalider()
                '_scenarioCentral.resultats = Nothing
            End If
            RaiseEvent EtatCalculScenCentralChanged(Me, e)
        End Sub
        Private Sub onSimulationsEtatCalculChanged(ByVal sender As Object, ByVal e As EventArgs)
            RaiseEvent EtatCalculSimulationsChanged(Me, e)
        End Sub
        Private Sub onParametreChanged(ByVal sender As Object, ByVal e As EventArgs)
            _scenarioCentral.Invalider()
        End Sub

        ''' <summary>
        ''' Le traitement en entrée du moteur de calcul a été modifié. La notification est envoyée par la liste de
        ''' traitements OMANE
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub onTraitEntree_EtatCalculDataTableChanged(ByVal sender As Object, ByVal e As EventArgs) Implements IIntegMoteur_MethodeEqTarif.onTraitEntree_EtatCalculDataTableChanged
            If CType(sender, RequeteBDD).EtatCalcul_DataTable = ValueEtatCalcul.A_MAJ Then
                Me._scenarioCentral.Invalider()
            End If
        End Sub

#End Region

#Region "Evènements générés"
        Public Event EtatCalculScenCentralChanged As EventHandler Implements IIntegMoteur_MethodeEqTarif.EtatCalculScenCentralChanged
        Public Event EtatCalculSimulationsChanged As EventHandler Implements IIntegMoteur_MethodeEqTarif.EtatCalculSimulationsChanged
#End Region

    End Class

End Namespace
